/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package jfinance.UI;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Panel;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.UIManager;
import jfinance.Account;
import jfinance.AccountsModel;
import jfinance.AccountsModelIOController;
import jfinance.AccountsController;
import jfinance.Transaction;
import jfinance.View;


/**
 *
 * @author efim
 */
public class MainFrame extends javax.swing.JFrame implements View {

    /**
     * Creates new form MainFrame
     */
    
    public MainFrame() {        
        initComponents(); 
        model = new AccountsModel();        
        saver = new AccountsModelIOController();   
        controller = new AccountsController(model,this);
        
    }

    private AccountsController controller;
    private AccountsModel model;
    private AccountsModelIOController saver;
    private DefaultListModel<Account> accountsModel = new DefaultListModel<Account>();
    private DefaultListModel<Transaction> transactionsModel = new DefaultListModel<>();

    public void error(String text) {
        ErrDialog err = new ErrDialog(this, true, text);
        err.setVisible(true);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jTabbedPane1 = new javax.swing.JTabbedPane();
        accountsPanel = new javax.swing.JPanel();
        accountToolBar = new javax.swing.JToolBar();
        addAccountButton = new javax.swing.JButton();
        editAccountButton = new javax.swing.JButton();
        deleteAccountButton = new javax.swing.JButton();
        chartAccountButton = new javax.swing.JButton();
        accountScrollPane = new javax.swing.JScrollPane();
        accountsList = new javax.swing.JList();
        transactionsPanel = new javax.swing.JPanel();
        jToolBar1 = new javax.swing.JToolBar();
        jScrollPane2 = new javax.swing.JScrollPane();
        jList2 = new javax.swing.JList();
        menuBar = new javax.swing.JMenuBar();
        fileMenuButton = new javax.swing.JMenu();
        openFileButton = new javax.swing.JMenuItem();
        saveFileButton = new javax.swing.JMenuItem();
        saveasFileButton = new javax.swing.JMenuItem();
        editMenuButton = new javax.swing.JMenu();
        otchetMenuButton = new javax.swing.JMenu();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("JellyFinance");

        accountToolBar.setRollover(true);

        addAccountButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/jfinance/UI/mini_icons/add.png"))); // NOI18N
        addAccountButton.setToolTipText("Добавить счёт");
        addAccountButton.setFocusable(false);
        addAccountButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        addAccountButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        addAccountButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addAccountButtonActionPerformed(evt);
            }
        });
        accountToolBar.add(addAccountButton);

        editAccountButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/jfinance/UI/mini_icons/edit.png"))); // NOI18N
        editAccountButton.setToolTipText("Редактировать");
        editAccountButton.setFocusable(false);
        editAccountButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        editAccountButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        editAccountButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                editAccountButtonActionPerformed(evt);
            }
        });
        accountToolBar.add(editAccountButton);

        deleteAccountButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/jfinance/UI/mini_icons/delete.png"))); // NOI18N
        deleteAccountButton.setToolTipText("Удалить");
        deleteAccountButton.setFocusable(false);
        deleteAccountButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        deleteAccountButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        deleteAccountButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteAccountButtonActionPerformed(evt);
            }
        });
        accountToolBar.add(deleteAccountButton);

        chartAccountButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/jfinance/UI/mini_icons/pie_chart.png"))); // NOI18N
        chartAccountButton.setToolTipText("Статистика");
        chartAccountButton.setFocusable(false);
        chartAccountButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        chartAccountButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        accountToolBar.add(chartAccountButton);

        accountScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        accountsList.setModel(accountsModel);
        accountsList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        accountsList.setAutoscrolls(false);
        accountsList.setCellRenderer(new ListCellRenderer(){
            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                Account v = (Account) value;
                AccountBeanForm lPanel = new AccountBeanForm(v);
                controller.addView(lPanel);

                if (isSelected) {
                    lPanel.setBackground(list.getSelectionBackground());
                    lPanel.setForeground(list.getSelectionForeground());
                } else {
                    lPanel.setBackground(list.getBackground());
                    lPanel.setForeground(list.getForeground());
                }

                return lPanel;
            }
        });
        accountScrollPane.setViewportView(accountsList);

        javax.swing.GroupLayout accountsPanelLayout = new javax.swing.GroupLayout(accountsPanel);
        accountsPanel.setLayout(accountsPanelLayout);
        accountsPanelLayout.setHorizontalGroup(
            accountsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(accountToolBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(accountScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 310, Short.MAX_VALUE)
        );
        accountsPanelLayout.setVerticalGroup(
            accountsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(accountsPanelLayout.createSequentialGroup()
                .addComponent(accountToolBar, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(accountScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE))
        );

        jTabbedPane1.addTab("Счета", accountsPanel);

        jToolBar1.setRollover(true);

        jList2.setModel(transactionsModel);
        jList2.setCellRenderer(new ListCellRenderer(){
            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                Transaction v = (Transaction) value;
                TransactionBeanForm lPanel = new TransactionBeanForm(v);

                if (isSelected) {
                    lPanel.setBackground(list.getSelectionBackground());
                    lPanel.setForeground(list.getSelectionForeground());
                } else {
                    lPanel.setBackground(list.getBackground());
                    lPanel.setForeground(list.getForeground());
                }

                return lPanel;
            }
        });
        jScrollPane2.setViewportView(jList2);

        javax.swing.GroupLayout transactionsPanelLayout = new javax.swing.GroupLayout(transactionsPanel);
        transactionsPanel.setLayout(transactionsPanelLayout);
        transactionsPanelLayout.setHorizontalGroup(
            transactionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 310, Short.MAX_VALUE)
        );
        transactionsPanelLayout.setVerticalGroup(
            transactionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(transactionsPanelLayout.createSequentialGroup()
                .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE))
        );

        jTabbedPane1.addTab("Транзакции", transactionsPanel);

        fileMenuButton.setText("Файл");

        openFileButton.setText("Открыть...");
        openFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openFileButtonActionPerformed(evt);
            }
        });
        fileMenuButton.add(openFileButton);

        saveFileButton.setText("Сохранить");
        saveFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveFileButtonActionPerformed(evt);
            }
        });
        fileMenuButton.add(saveFileButton);

        saveasFileButton.setText("Сохранить как...");
        fileMenuButton.add(saveasFileButton);

        menuBar.add(fileMenuButton);

        editMenuButton.setText("Правка");
        menuBar.add(editMenuButton);

        otchetMenuButton.setText("Отчеты");
        menuBar.add(otchetMenuButton);

        setJMenuBar(menuBar);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jTabbedPane1)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jTabbedPane1)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void addAccountButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addAccountButtonActionPerformed
        // TODO add your handling code here:
        AccountDialog dialog = new AccountDialog(this, true,controller);
        dialog.setVisible(true);
        
    }//GEN-LAST:event_addAccountButtonActionPerformed

    private void deleteAccountButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteAccountButtonActionPerformed
        // TODO add your handling code here:
        if (accountsList.getSelectedIndex() == -1) {
            return;
        }
        QuestionlDialog dialog = new QuestionlDialog(this, true, "Вы действительно хотите удалить счёт?");
        dialog.setVisible(true);
        if (dialog.getReturnStatus() == QuestionlDialog.RET_OK) {
            Account account = (Account) accountsList.getSelectedValue();
            controller.deleteAccount(account);
        }
    }//GEN-LAST:event_deleteAccountButtonActionPerformed

    private void editAccountButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editAccountButtonActionPerformed
        // TODO add your handling code here:
        if(accountsList.getSelectedIndex()==-1)return;
        Account account = (Account)accountsList.getSelectedValue();
        AccountFrame frame = new AccountFrame(account);
        frame.setVisible(true);        
    }//GEN-LAST:event_editAccountButtonActionPerformed

    private void saveFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveFileButtonActionPerformed
        // TODO add your handling code here:
        try {           
            saver.save(controller.getAccounts());
        } catch (IOException ex) {
            error("Не удалось сохранить!");
        }
    }//GEN-LAST:event_saveFileButtonActionPerformed

    private void openFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openFileButtonActionPerformed
        // TODO add your handling code here:
        JFileChooser ch = new JFileChooser();
        if(ch.showOpenDialog(this)==JFileChooser.APPROVE_OPTION){
            saver.setFactory(new AccountsModel.FileIOFactory(ch.getSelectedFile().getName()));
            try {
                controller = new AccountsController(new AccountsModel(),this);
                List<Account> list = saver.load();
                for(Account a:list){
                    controller.addAccount(a);
                }
            } catch (IOException ex) {
                Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ClassCastException ex) {
                Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }//GEN-LAST:event_openFileButtonActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Windows".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MainFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MainFrame().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane accountScrollPane;
    private javax.swing.JToolBar accountToolBar;
    private javax.swing.JList accountsList;
    private javax.swing.JPanel accountsPanel;
    private javax.swing.JButton addAccountButton;
    private javax.swing.JButton chartAccountButton;
    private javax.swing.JButton deleteAccountButton;
    private javax.swing.JButton editAccountButton;
    private javax.swing.JMenu editMenuButton;
    private javax.swing.JMenu fileMenuButton;
    private javax.swing.JList jList2;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JMenuItem openFileButton;
    private javax.swing.JMenu otchetMenuButton;
    private javax.swing.JMenuItem saveFileButton;
    private javax.swing.JMenuItem saveasFileButton;
    private javax.swing.JPanel transactionsPanel;
    // End of variables declaration//GEN-END:variables

    @Override
    public void modelPropertyChange(PropertyChangeEvent evt) {
       switch(evt.getPropertyName()){
           case AccountsModel.NEW_ACCOUNT_EVENT :
               Account account = (Account)evt.getNewValue();
               accountsModel.addElement(account);
               for(Transaction t:account.getTransactions()){
                   transactionsModel.addElement(t);
               }
               break;
           case AccountsModel.SET_ACCOUNT_EVENT:
               int index = accountsModel.indexOf(evt.getOldValue());
               accountsModel.set(index, (Account)evt.getNewValue());
               break;
           case AccountsModel.DELETE_ACCOUNT_EVENT:
               accountsModel.removeElement((Account)evt.getOldValue());
               break;
           case Account.DELETE_TRANSACTION_EVENT:
               transactionsModel.removeElement(evt.getOldValue());
               break;
           case Account.NEW_TRANSACTION_EVENT:
               transactionsModel.addElement((Transaction)evt.getNewValue());
               break;
           case Account.SET_TRANSACTION_EVENT:
               int i = transactionsModel.indexOf(evt.getOldValue());
               transactionsModel.set(i, (Transaction)evt.getNewValue());
               break;
           
       }
    }
}
